<template>
  <div class="ebook-reader">
    <div id="read"></div>
    <div
      class="ebook-reader-mask"
      @click="onMaskClick"
      @touchmove="move"
      @touchend="moveEnd"
      @mousedown.left="onMouseEnter"
      @mousemove.left="onMouseMove"
      @mouseup.left="onMouseEnd"
    ></div>
  </div>
</template>

<script>
  import { ebookMixin } from '../../utils/mixin'
  import Epub from 'epubjs'
  import {
    getFontFamily,
    getFontSize,
    getLocation,
    getTheme,
    saveFontFamily,
    saveFontSize,
    saveTheme
  } from '../../utils/localStorage'
  import { flatten } from '../../utils/book'
  import { getLocalForage } from '../../utils/localForage'

  global.ePub = Epub
  export default {
    mixins: [ebookMixin],
    methods: {
      // 1、鼠标进入
      // 2、鼠标进入后的移动
      // 3、鼠标从移动状态松手
      // 4、鼠标还原
      onMouseEnd(e) {
        if (this.mouseState === 2) {
          this.setOffsetY(0)
          this.firstOffsetY = null
          this.mouseState = 3
        } else {
          this.mouseState = 4
        }
        // 防止点击之后没有效果
        const time = e.timeStamp - this.mouseStartTime
        if (time < 100) this.mouseState = 4
        e.preventDefault()
        e.stopPropagation()
      },
      onMouseMove(e) {
        if (this.mouseState === 1) {
          this.mouseState = 2
        } else if (this.mouseState === 2) {
          let offsetY = 0
          if (this.firstOffsetY) {
            offsetY = e.clientY - this.firstOffsetY
            this.setOffsetY(offsetY)
          } else {
            this.firstOffsetY = e.clientY
          }
        }
        e.preventDefault()
        e.stopPropagation()
      },
      onMouseEnter(e) {
        this.mouseState = 1
        this.mouseStartTime = e.timeStamp
        e.preventDefault()
        e.stopPropagation()
      },
      move(e) {
        // 侦测偏移量
        let offsetY = 0
        if (this.firstOffsetY) {
          offsetY = e.changedTouches[0].clientY - this.firstOffsetY
          this.setOffsetY(offsetY)
        } else {
          this.firstOffsetY = e.changedTouches[0].clientY
        }
        e.preventDefault()
        e.stopPropagation()
      },
      moveEnd(e) {
        // 清空偏移量
        this.setOffsetY(0)
        this.firstOffsetY = null
      },
      onMaskClick(e) {
        // 点击切换文章页数
        if (this.mouseState && (this.mouseState === 2 || this.mouseState === 3)) return
        const offsetX = e.offsetX
        const width = window.innerWidth
        if (offsetX > 0 && offsetX < width * 0.3) {
          this.prevPage()
        } else if (offsetX > 0 && offsetX > width * 0.7) {
          this.nextPage()
        } else {
          this.toggleTitleAndMenu()
        }
      },
      prevPage() {
        if (this.rendition) {
          this.rendition.prev().then(() => {
            this.refreshLocation()
          })
          this.hideTitleAndMenu()
        }
      },
      nextPage() {
        if (this.rendition) {
          this.rendition.next().then(() => {
            this.refreshLocation()
          })
          this.hideTitleAndMenu()
        }
      },
      toggleTitleAndMenu() {
        if (this.menuVisible) {
          this.setSettingVisible(-1)
          this.setFontFamilyVisible(false)
        }
        this.setMenuVisible(!this.menuVisible)
      },
      initTheme() {
        let defaultTheme = getTheme(this.fileName)
        if (!defaultTheme) {
          defaultTheme = this.themeList[0].name
          saveTheme(this.fileName, defaultTheme)
        }
        this.setDefaultTheme(defaultTheme)
        this.themeList.forEach((theme) => {
          this.rendition.themes.register(theme.name, theme.style)
        })
        this.rendition.themes.select(defaultTheme)
      },
      initFontSize() {
        let fontSize = getFontSize(this.fileName)
        if (!fontSize) {
          saveFontSize(this.fileName, this.defaultFontSize) //  缓存字号
        } else {
          this.rendition.themes.fontSize(fontSize) // 有缓存字体则用缓存字号
          this.setDefaultFontSize(fontSize)
        }
      },
      initFontFamily() {
        let font = getFontFamily(this.fileName)
        if (!font) {
          saveFontFamily(this.fileName, this.defaultFontFamily) //  缓存字体
        } else {
          this.rendition.themes.font(font) // 有缓存字体则用缓存字体
          this.setDefaultFontFamily(font)
        }
      },
      initRendition() {
        // 初始化渲染
        this.rendition = this.book.renderTo('read', {
          width: innerWidth,
          height: innerHeight,
          method: 'default'
          // flow: 'scrolled' 滚动条模式
        })
        // getLocation 保存阅读进度
        const location = getLocation(this.fileName)
        this.display(location, () => {
          this.initTheme()
          this.initFontSize()
          this.initFontFamily()
          this.initGlobalStyle()
        })
        // 当我们阅读器渲染完之后我们会调用这个方法
        this.rendition.hooks.content.register((contents) => {
          Promise.all([
            contents.addStylesheet(`${process.env.VUE_APP_RES_URL}/fonts/daysOne.css`),
            contents.addStylesheet(`${process.env.VUE_APP_RES_URL}/fonts/cabin.css`),
            contents.addStylesheet(`${process.env.VUE_APP_RES_URL}/fonts/montserrat.css`),
            contents.addStylesheet(`${process.env.VUE_APP_RES_URL}/fonts/tangerine.css`)
          ]).then(() => {})
        })
      },
      initGesture() {
        // 手势翻页操作
        this.rendition.on('touchstart', (event) => {
          this.touchStarX = event.changedTouches[0].clientX
          this.touchStarTime = event.timeStamp
        })
        this.rendition.on('touchend', (event) => {
          const offsetX = event.changedTouches[0].clientX - this.touchStarX
          const time = event.timeStamp - this.touchStarTime
          if (time < 500 && offsetX > 40) {
            this.prevPage()
          } else if (time < 500 && offsetX < -40) {
            this.nextPage()
          } else {
            this.toggleTitleAndMenu()
          }
          event.preventDefault()
          event.stopPropagation()
        })
      },
      parseBook() {
        // 获取图片链接
        this.book.loaded.cover.then((cover) => {
          this.book.archive.createUrl(cover).then((url) => {
            this.setCover(url)
          })
        })
        this.book.loaded.metadata.then((metadata) => {
          this.setMetadata(metadata)
        })
        this.book.loaded.navigation.then((nav) => {
          const navItem = flatten(nav.toc)
          function find(item, level = 0) {
            return !item.parent
              ? level
              : find(
                  navItem.filter((parentItem) => parentItem.id === item.parent)[0],
                  ++level
                )
          }
          navItem.forEach((item) => {
            item.level = find(item)
          })
          this.setNavigation(navItem)
        })
      },
      initEpub(url) {
        this.book = new Epub(url)
        this.setCurrentBook(this.book)
        this.initRendition()
        // this.initGesture()
        this.parseBook()
        this.book.ready
          .then(() => {
            // 分页处理
            return this.book.locations.generate(
              750 * (window.innerWidth / 375) * (getFontSize(this.fileName) / 16)
            )
          })
          .then((locations) => {
            this.navigation.forEach((nav) => {
              nav.pagelist = []
            })
            locations.forEach((item) => {
              const loc = item.match(/\[(.*)\]!/)[1]
              this.navigation.forEach((nav) => {
                if (nav.href) {
                  const href = nav.href.match(/^(.*)\.html$/)
                  if (href) {
                    if (href[1] === loc) {
                      nav.pagelist.push(item)
                    }
                  }
                }
              })
              let currentPage = 1
              this.navigation.forEach((nav, index) => {
                if (index === 0) {
                  nav.page = 1
                } else {
                  nav.page = currentPage
                }
                currentPage += nav.pagelist.length + 1
              })
            })
            this.setPagelist(locations)
            this.setBookAvailable(true)
            this.refreshLocation()
          })
      }
    },
    mounted() {
      const books = this.$route.params.fileName.split('|')
      const fileName = books[1]
      // 拿到fileName,在LocalForage中能不能找到
      getLocalForage(fileName, (err, blob) => {
        if (!err && blob) {
          // 没有错误，同时blob对象存在时
          this.setFileName(books.join('/')).then(() => {
            this.initEpub(blob)
          })
        } else {
          // 没有获取到电子书,就再去下载
          this.setFileName(books.join('/')).then(() => {
            const url = `${process.env.VUE_APP_EPUB_URL}/` + this.fileName + '.epub'
            this.initEpub(url)
          })
        }
      })
    }
  }
</script>

<style lang="scss" rel="stylesheet/scss" scoped>
  @import '../../assets/styles/global.scss';
  .ebook-reader {
    width: 100%;
    height: 100%;
    overflow: hidden;
    .ebook-reader-mask {
      position: absolute;
      z-index: 150;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
    }
  }
</style>
